/*
 * Copyright (c) 2022-2023 cetcclout Co., Ltd All rights reserved.
 * Sensor Adapter is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package com.cetccloud.cimp.adapter.server.mqtt.publish;

import cn.hutool.json.JSONObject;

import com.cetccloud.cimp.adapter.server.mqtt.MqttSign;
import com.cetccloud.cimp.adapter.server.mqtt.SystemContext;
import com.cetccloud.cimp.common.util.SensorStringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.UUID;

/** 
 * @author
 * @apiNote 创建mqtt客户端链接
 * @date 2022/12/29 16:35       
 */
@Component
public class MqttPublishClient {

    @Value("${application.mqtt.broker}")
    private String broker;
    @Value("${application.mqtt.pwd}")
    private String pwd;
    @Value("${application.mqtt.topic}")
    private String topicPre;

    @Value("${spring.profiles.active}")
    private String active;
    int qos = 2;
    private static final InternalLogger logger = InternalLoggerFactory.getInstance(MqttPublishClient.class);

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    private static MqttAsyncClient mqttAsyncClient;

    /**
     * 初始化MQTT链接客户端
     */
    @PostConstruct
    public void init() {
        String clientId    = SensorStringUtils.PUBLISH_PREFIX + "monitor-" + active + "-" + UUID.randomUUID();
        MemoryPersistence persistence = new MemoryPersistence();

        try {
            mqttAsyncClient = new MqttAsyncClient(broker, clientId, persistence);
            MqttConnectOptions connOpts = new MqttConnectOptions();
            connOpts.setAutomaticReconnect(true);
            connOpts.setCleanSession(true);
            connOpts.setUserName(MqttSign.getUsername());
            connOpts.setPassword(pwd.toCharArray());
            connOpts.setMaxInflight(1000);
            IMqttToken connToken  = mqttAsyncClient.connect(connOpts);
            connToken.waitForCompletion(1000L * 20);
            logger.info("初始化原始数据包发布地址：{}", mqttAsyncClient.getClientId());
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    /**
     * AT指令回传
     */
    public void publishAtBackData(JSONObject message, String dtuId) {
        try {
            String topic = SensorStringUtils.SUB_CMD_BACK_TOPIC + dtuId;
            MqttMessage mqttMessage = new MqttMessage(OBJECT_MAPPER.writeValueAsString(message).getBytes());
            mqttMessage.setQos(qos);
            mqttAsyncClient.publish(topic, mqttMessage);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            logger.error("ERROR: {}",e.getMessage());
        } catch (MqttException e) {
            e.printStackTrace();
            logger.error("ERROR: {}",e.getMessage());
        }
    }

    /**
     * 回传服务启动结果状态    
     */
    public void publishServerStatus(JSONObject message) {
        try {
            MqttMessage mqttMessage = new MqttMessage(OBJECT_MAPPER.writeValueAsString(message).getBytes());
            mqttMessage.setQos(qos);
            mqttAsyncClient.publish(SystemContext.MqTopic.PUB_START_OR_STOP_TOPIC, mqttMessage);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            logger.error("ERROR: {}",e.getMessage());
        } catch (MqttException e) {
            e.printStackTrace();
            logger.error("ERROR: {}",e.getMessage());
        }
    }
}
